/**
 * FractalAnimator.java
 * @author: liuex
 * 2008-1-6 ����03:32:40
 *
 * note: 
 */
package lex.fractal.swing.common;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;

import javax.swing.JPanel;

import lex.fractal.algorithm.Fractal;

public class FractalAnimator extends JPanel {
	public final static int DEFAULT_DELAY = 500;
	public final static int MAX_DELAY = 1025;
	public final static int MIN_DELAY = 25;
	public final static int STEP = 50;
	public final static Color PANEL_COLOR = new Color(255, 255, 225);
	// =================================
	private Insets insets = new Insets(0, 0, 0, 0);
	private Fractal fractal;
	private volatile int depth = 0;
	private volatile int delay = DEFAULT_DELAY;
	private volatile FractalThread thread;

	public FractalAnimator(Fractal fractal) {
		this.fractal = fractal;
	}

	public void paintComponent(Graphics g) {
		insets = this.getInsets(insets);
		int width = getWidth() - insets.left - insets.right;
		int height = getHeight() - insets.top - insets.bottom;
		Graphics2D g2d = (Graphics2D) g.create();
		g2d.translate(insets.left, insets.top);
		g2d.setColor(PANEL_COLOR);
		g2d.fillRect(0, 0, width, height);
		g2d.setColor(Color.black);
		fractal.generate(g2d, depth, width, height);
		g2d.dispose();
	}

	public void setDelay(int ms) {
		if (ms <= 0)
			throw new IllegalArgumentException(ms + " < MIN_DELAY");
		this.delay = ms;
	}

	public void start() {
		this.stop();
		thread = new FractalThread();
		thread.start();
	}

	public void stop() {
		if (null == thread)
			return;
		thread.stopAnimate();
		thread = null;
	}

	class FractalThread extends Thread {
		private boolean stop = false;

		void stopAnimate() {
			stop = true;
		}

		public void run() {
			Thread currThd = Thread.currentThread();
			while (false == stop && currThd == this) {
				if (++depth > fractal.getMaximalDepth())
					depth = 0;
				repaint();
				try {
					Thread.sleep(delay);
				} catch (InterruptedException e) {
					stopAnimate();
				}
			}
		}
	}
}
